﻿// owner 蒋家伟

#pragma once
// std
#include <mutex>
#include <functional>

// jsdk
#include "ITaskManager.h"
#include "IHandler.h"
#include "ITaskExectutable.h"

namespace jsdk
{
    class ITask;
    class TaskGroup;
    class ITaskDescription;
    class TaskTransferWorker;
    using TaskTaskExectutableCreator = std::function<OwnerPtr<ITaskExectutable>(void)>;

    class TaskManager : public ITaskManager, public IHandler
    {
        friend class TaskTransferWorker;
    public:
        /// \ brief 获取一个可用的任务ID
        /// \ return 一个有效的taskID
        static TaskId getAvailableTaskId();
        static TaskManager& get();
        TaskManager();
        ~TaskManager();

    public:
        /// \ brief 注册任务的执行者
        /// \ in taskDescription 任务描述
        /// \ in taskExectutableCreator 任务的执行者创建者
        bool registerTaskExctutable(const std::wstring& taskDescription, TaskTaskExectutableCreator taskExectutableCreator);
        OwnerPtr<ITaskExectutable> getTaskExectutable(const ITaskDescription& pTaskDescription);

    private:
        // 继承 ITaskManager
        virtual OwnerPtr<ITask> getTaskById(const TaskId& taskId) override;
        virtual TaskId addAsyncTask(OwnerPtr<ITask> opTask) override;
        virtual void addSyncTask(OwnerPtr<ITask> opTask) override;

        // 继承IHandler
        virtual void On(const IArgs* pArgs) override;

#pragma region TaskTransferWorker 使用
    private:
        /// \ 处理多线程的竞争导致的部分任务未触发的情况
        std::vector<ITask*> getAllTaskWithoutDelayTime();
        /// \ 拆分任务组，将任务组中的任务放到任务通知队列里面，然后删除当前任务组
        std::vector<TaskId> splitTaskGroup(TaskGroup* pTaskGroup);
        /// \ 通过任务ID获取当前任务的可写指针
        ITask* getTaskFWByTaskId(const TaskId& taskId);
        /// \ 通过任务ID获取当前任务的只读指针
        const ITask* getTaskByTaskId(const TaskId& taskId) const;
#pragma region TaskTransferWorker 使用

    private:
        std::mutex m_taskMutex;
        std::map<TaskId, OwnerPtr<ITask>> m_taskIdToTaskList;         // 还未通知的队列
        std::map<TaskId, OwnerPtr<ITask>> m_taskIdToNotifiedTaskList; // 已经被通知的队列
        std::map<std::wstring, TaskTaskExectutableCreator> m_taskDescriptionToExectutableMap;
    };
}